<?php

declare(strict_types=1);

namespace App\CustHub\Service;

use App\Common\Constants\StorageModeConstants;
use App\Common\Helpers\QrCode;
use App\Common\Robot\Robot;
use App\Common\Service\ShortChainService;
use App\CustHub\Constants\RoomInviteLogTypeConstants;
use App\CustHub\Constants\RoomTaskCenterTypeConstants;
use App\CustHub\Dto\RoomTcContentDto;
use App\CustHub\Mapper\ChContactMapper;
use App\CustHub\Mapper\ChRobotMapper;
use App\CustHub\Mapper\ChRoomCodeMapper;
use App\CustHub\Mapper\ChRoomCodeRecordMapper;
use App\CustHub\Mapper\ChRoomMapper;
use App\CustHub\Model\ChRoom;
use App\CustHub\Model\ChRoomCodeRoomRelation;
use App\CustHub\Model\ChRoomMember;
use App\Robot\Dto\CommonJobDto;
use App\Robot\Job\CommonJob;
use App\Robot\Service\RobotApiService;
use App\Setting\Service\SettingConfigService;
use Carbon\Carbon;
use Hyperf\DbConnection\Db;
use Hyperf\Di\Annotation\Inject;
use Hyperf\Paginator\LengthAwarePaginator;
use Hyperf\Redis\Redis;
use Mine\Abstracts\AbstractService;
use Mine\Annotation\Transaction;
use Mine\Exception\NormalStatusException;
use Mine\MineCollection;
use Mine\MineModel;
use Mine\MineResponse;
use function Hyperf\Collection\collect;
use function Hyperf\Collection\data_get;
use function Hyperf\Coroutine\co;

class ChRoomCodeService extends AbstractService
{
    public $mapper;

    #[Inject]
    protected ChRoomTaskCenterService $ChRoomTaskCenterService;
    #[Inject]
    protected ChRoomCodeRecordMapper $codeRecordMapper;

    #[Inject]
    protected ChRoomMapper $roomMapper;

    #[Inject]
    protected ChRobotMapper $robotMapper;

    #[Inject]
    protected ChContactMapper $contactMapper;

    #[Inject]
    protected ChRoomCodeRoomRelation $roomRelation;

    #[Inject]
    protected ChRoomService $roomService;

    #[Inject]
    protected redis $redis;

    protected string $roomNameNumberPrefix = 'room_name_number:';

    public function __construct(ChRoomCodeMapper $mapper)
    {
        $this->mapper = $mapper;
    }

    /**
     * 更新用户进/退群状态
     * $params $joinType 1-进群 2-退群
     * @return mixed
     */
    #[Transaction]
    public function saveRelationStatus(mixed $userIds,$roomId,$mainUid,$uid,$roomWxid,$joinType):void
    {
        var_dump('渠道活码进群退群');
        $relationList = $this->roomRelation::query()->where('main_uid', $mainUid)->where('room_wxid', $roomWxid)->get();
        if($relationList ->isEmpty()) return;
        $data=[
            'room_id' => $roomId,
            'room_wxid' => $roomWxid,
        ];
//        if($joinType==1){
//            $members = ChRoomMember::query()
//                ->where('room_wxid', $roomWxid)
//                ->whereIn('user_id', $userIds)
//                ->where('join_scene', 3) // 仅处理扫码入群的用户
//                ->count();
//            if($members==0){
//                return false;
//            }
//        }
//        $joinType==1 && $data['is_enter_room']=1;
//        $joinType==2 && $data['is_out_room']=1;
        foreach ($relationList as $relation){
            $attributes=[
                'main_uid' => $relation->main_uid,
                'uid' => $relation->uid,
                'relation_id' => $relation->id,
                'code_id' => $relation->code_id,
            ];
            if($joinType==1){
                $attributes['is_enter_room']=1;
            }
            if($joinType==2){
                $attributes['is_out_room']=1;
            }
            $newUserIds=[];
            if(isset($userIds)){
                foreach ($userIds as $userId){
                    $attributes['user_id']=$userId;
                    $record=$this->codeRecordMapper->model::query()->where($attributes)->first();
                    if(!empty($record)){
                        $record->update($data);
                    }else{
                        $newUserIds[]=$userId;
                        $this->codeRecordMapper->model::query()->create(array_merge($attributes,$data));
                    }
                }
                $count=count($newUserIds);
            }else{
                $attributes['user_id']=0;
                $this->codeRecordMapper->model::query()->create(array_merge($attributes,$data));
                $count=1;
            }


            if($joinType==1 && $count > 0){
                $this->roomRelation::query()->where(['id'=>$relation['id']])->update([
                    'daily_join_visit' => Db::raw('daily_join_visit+'.$count),
                    'join_visit' => Db::raw('join_visit+'.$count),
                ]);
                $this->mapper->update($relation['code_id'], [
                    'daily_join_visit' => Db::raw('daily_join_visit+'.$count),
                    'join_visit' => Db::raw('join_visit+'.$count),
                ]);
            }
            if($joinType==2 && $count> 0){
                $this->roomRelation::query()->where(['id'=>$relation['id']])->update([
                    'daily_out_visit' => Db::raw('daily_out_visit+'.$count),
                    'out_visit' => Db::raw('out_visit+'.$count),
                ]);
                $this->mapper->update($relation['code_id'], [
                    'daily_out_visit' => Db::raw('daily_out_visit+'.$count),
                    'out_visit' => Db::raw('out_visit+'.$count),
                ]);
            }

        }
    }

    public function roomRelatoinOperation(array $params)
    {
        return $this->roomRelation->where('id', $params['id'])->update(['status' => $params['status']]);
    }
//
//    public function roomCodeOperation(array $params)
//    {
//        $id=$params['id'];
//        $this->mapper->where('id',$id)->first();
//        $upStatus=$params['status']==1?2:1;
//        return $this->mapper->where('id',$id)->update(['status'=>$upStatus]);
//    }

    public function getRoomCodeList(array $params)
    {
        $uid = (int)($params['uid'] ?? 0);
        $pageSize = (int)($params['page_size'] ?? MineModel::PAGE_SIZE);
        $query = $this->mapper->model::query()->from('ch_room_code as rc')
            ->with(['user' => function ($q) {
                $q->select('id', 'nickname', 'avatar');
            }])
            ->leftJoin('ch_room_code_room_relation as rcr', 'rc.id', '=', 'rcr.code_id')
            ->select([
                'rc.id',
                'rc.code',
                'rc.code_name',
                'rc.status',
                'rc.uid',
                'rc.main_uid',
                'rc.created_at',
                'rc.poster',
                'rc.render_url',
                'rc.out_visit',
                'rc.daily_out_visit',
                // 根据实际字段补充其他 rc. 字段
                Db::raw('rc.total_visit as visit_count'),
                Db::raw('rc.daily_visit as daily_visit_count'),
                Db::raw('rc.join_visit as join_visit_count'),
                Db::raw('rc.daily_join_visit as daily_join_visit_count'),
                Db::raw('(
            SELECT COUNT(*) 
            FROM ch_room_code_room_relation 
            WHERE code_id = rc.id 
            AND allocate_status = 1 
            AND status = 1
        ) as available_room_total'),
                Db::raw('(
            SELECT COUNT(*) 
            FROM ch_room_code_room_relation 
            WHERE code_id = rc.id
        ) as room_total'),
                Db::raw('(
            SELECT COUNT(*) 
            FROM ch_room_code_room_relation 
            WHERE code_id = rc.id 
            AND is_new_create = 1
        ) as new_create_total'),
            ])
            ->orderBy('rc.id','desc')
            ->groupBy('rc.id');
        $data = $this->mapper->handleSearch2($query, $params)->paginate($pageSize);
        $data->getCollection()->transform(function ($item) {

            return $item;
        });
        return $this->mapper->setPaginate($data);
    }

    public function getRoomCodeDetail($params)
    {
        //$relation = $this->roomRelation::query()->find($params['id']);
        $id = $params['id'];
        $code = $this->mapper->model::with(['room_list' => function ($q) {
            $q->from('ch_room_code_room_relation')->leftJoin('ch_room as r', 'ch_room_code_room_relation.room_id', '=', 'r.id')->selectRaw("ch_room_code_room_relation.*,r.room_name,r.room_avatar_url")->where('ch_room_code_room_relation.is_new_create', 0);
        }])
            ->whereRaw('id=' . $id)
            ->first();

        if (!$code) {
            throw new NormalStatusException('群活码不存在');
        }

        // 创建临时变量处理配置数据
        $roomRuleCfg = $code->room_rule_cfg ?? [];

        // 处理机器人信息（保持原逻辑）
        $robotIds = $roomRuleCfg['create_room_cfg']['robot_ids'] ?? [];
        if (!empty($robotIds)) {
            $robots = $this->robotMapper->findByIds($robotIds, 'id, nickname as robot_name, avatar');
            $roomRuleCfg['create_room_cfg']['robots'] = $robots->keyBy('id');
        }

        // 处理固定成员信息（优化版）
        $fixedMembers = $roomRuleCfg['create_room_cfg']['create_room_rule']['fixed_members'] ?? [];
//        if (!empty($fixedMembers)) {
//            $userMap = [];
//
//            // 步骤1：按robot_id分组收集user_ids
//            $robotUserGroups = [];
//            foreach ($fixedMembers as $member) {
//                if (!empty($member['user_ids']) && isset($member['robot_id'])) {
//                    $robotId = $member['robot_id'];
//                    $robotUserGroups[$robotId] = array_merge(
//                        $robotUserGroups[$robotId] ?? [],
//                        $member['user_ids']
//                    );
//                }
//            }
//
//            // 步骤2：批量查询
//            if (!empty($robotUserGroups)) {
//                $users = $this->contactMapper->findBatchByRobotIdAndUserIds($robotUserGroups);
//
//                foreach ($users as $robotId => $userGroup) {
//                    foreach ($userGroup as $userId => $user) {
//                        $userMap[$robotId][$userId] = [
//                            'user_id' => $userId,
//                            'name' => $user->name,
//                            'avatar' => $user->avatar
//                        ];
//                    }
//                }
//            }
//
//            // 步骤3：处理成员数据
//            foreach ($fixedMembers as &$member) {
//                // 处理机器人信息
//                if (isset($member['robot_id'])) {
//                    $robot = $robots[$member['robot_id']] ?? null;
//                    $member['robot_name'] = $robot->name ?? '';
//                    $member['robot_avatar'] = $robot->avatar ?? '';
//                }
//
//                // 处理用户信息
//                $member['users'] = [];
//                if (!empty($member['user_ids']) && isset($member['robot_id'])) {
//                    foreach ($member['user_ids'] as $userId) {
//                        $member['users'][] = $userMap[$member['robot_id']][$userId] ?? [
//                            'user_id' => $userId,
//                            'name' => '',
//                            'avatar' => ''
//                        ];
//                    }
//                }
//                unset($member['user_ids']);
//            }
//
//            $roomRuleCfg['create_room_cfg']['create_room_rule']['fixed_members'] = $fixedMembers;
//        }

        // 将修改后的配置重新赋值给模型
        $code->room_rule_cfg = $roomRuleCfg;

        return $code;
    }

    public function getRoomCodeRoomDailyData($params)
    {
        $uid = (int)$params['uid'];
        $codeId = (int)$params['code_id'];
        $roomId = (int)$params['room_id'];
        $pageSize = (int)$params['page_size'] ?? MineModel::PAGE_SIZE;
        $query = $this->codeRecordMapper->getDailyCodeStatisticsByCodeIdAndRoomId($uid, $codeId, $roomId);
        $paginate = $query->paginate($pageSize);
        return $this->mapper->setPaginate($paginate);
    }

    public function getRoomCodeCodeData($params)
    {
        $uid = (int)$params['uid'];
        $codeId = (int)$params['code_id'];
        $time = $params['time'] ?? '';
        $pageSize = (int)$params['page_size'] ?? MineModel::PAGE_SIZE;

        $query = $this->codeRecordMapper->getRoomCodeStatisticsByTime($uid, $time);
        $paginate = $query->paginate($pageSize);

        return $this->mapper->setPaginate($paginate);
    }

    public function getBase64Code($params)
    {
        $uid = (int)$params['uid'];
        $codeId = (int)$params['code_id'];
        $codeInfo = $this->mapper->first(['id' => $codeId]);
        $base64code = '';
        $base64Poster = '';
        if (!empty($codeInfo->code)) {
            $imageData = base64_encode(file_get_contents($codeInfo->code));
            $path = parse_url($codeInfo->code, PHP_URL_PATH);
            $ext = pathinfo($path, PATHINFO_EXTENSION) ?? '';
            $base64code = 'data:image/' . $ext . ';base64,' . $imageData;
        }
        if (!empty($codeInfo->poster)) {
            $imageData = base64_encode(file_get_contents($codeInfo->poster));
            $path = parse_url($codeInfo->poster, PHP_URL_PATH);
            $ext = pathinfo($path, PATHINFO_EXTENSION) ?? '';
            $base64Poster = 'data:image/' . $ext . ';base64,' . $imageData;
        }
        return ['code' => $base64code, 'poster' => $base64Poster];
    }

    public function exportRoomCodeCodeData(array $params, string $dto)
    {
        $uid = (int)$params['uid'];
        $time = $params['time'] ?? '';

        $query = $this->codeRecordMapper->getRoomCodeStatisticsByTime($uid, $time);
        $list = $query->get();

        $transformedList = $list->map(function ($item) {
            return [
                'code_name' => $item->code_name,
                'new_rooms' => $item->new_rooms,
                'total_count' => $item->total_count,
                'enter_room_count' => $item->enter_room_count,
                'out_room_count' => $item->out_room_count,
            ];
        });

        // 默认文件名
        if (empty($filename)) {
            $filename = "群活码当日数据-" . Carbon::now()->format('Y-m-d_H-i-s');
        }

        return (new MineCollection())->export($dto, $filename, $transformedList->toArray());
    }

    public function getRoomCodeDailyData(array $params)
    {
        $uid = (int)$params['uid'];
        $codeId = (int)$params['code_id'];
        $timeRange = isset($params['time_range']) ? explode(',', $params['time_range']) : [];
        $pageSize = (int)$params['page_size'] ?? MineModel::PAGE_SIZE;

        $query = $this->codeRecordMapper->getDailyCodeStatisticsByCodeId($uid, $codeId, $timeRange);
        $paginate = $query->paginate($pageSize);

        return $this->mapper->setPaginate($paginate);
    }

    public function getDailyCodeStatisticsByRoomRelation(array $params)
    {
        $uid = (int)$params['uid'];
        $id = (int)$params['id'];
        $timeRange = isset($params['time_range']) ? explode(',', $params['time_range']) : [];
        $pageSize = (int)$params['page_size'] ?? MineModel::PAGE_SIZE;

        $query = $this->codeRecordMapper->getDailyCodeStatisticsByRoomRelation($id, $timeRange);
        $paginate = $query->paginate($pageSize);

        return $this->mapper->setPaginate($paginate);
    }

    public function exportRoomCodeRoomDailyData(array $params, string $dto)
    {
        if (empty($dto)) {
            return container()->get(MineResponse::class)->error('导出未指定DTO');
        }

        $uid = (int)$params['uid'] ?? 0;
        $codeId = (int)$params['code_id'] ?? 0;
        $timeRange = isset($params['time_range']) ? explode(',', $params['time_range']) : [];

        // 获取基础查询
        $query = $this->codeRecordMapper->getDailyCodeStatisticsByCodeId($uid, $codeId, $timeRange);
        $list = $query->get();

        // 数据转换
        $transformedList = $list->map(function ($item) {
            return [
                'date' => $item->date,
                'new_rooms' => $item->new_rooms,
                'total_count' => $item->total_count,
                'enter_room_count' => $item->enter_room_count,
                'out_room_count' => $item->out_room_count,
            ];
        });

        // 默认文件名
        if (empty($filename)) {
            $filename = "群活码日报-" . Carbon::now()->format('Y-m-d_H-i-s');
        }

        return (new MineCollection())->export($dto, $filename, $transformedList->toArray());
    }


    public function exportDailyCodeStatisticsByRoomRelation(array $params, string $dto)
    {
        if (empty($dto)) {
            return container()->get(MineResponse::class)->error('导出未指定DTO');
        }
        $id = (int)$params['id'];
        $timeRange = isset($params['time_range']) ? explode(',', $params['time_range']) : [];

        $query = $this->codeRecordMapper->getDailyCodeStatisticsByRoomRelation($id, $timeRange);
        $list = $query->get();


        // 数据转换
        $transformedList = $list->map(function ($item) {
            return [
                'date' => $item->date,
                'new_rooms' => $item->new_rooms,
                'total_count' => $item->total_count,
                'enter_room_count' => $item->enter_room_count,
                'out_room_count' => $item->out_room_count,
            ];
        });

        // 默认文件名
        if (empty($filename)) {
            $filename = "指定群活码日报-" . Carbon::now()->format('Y-m-d_H-i-s');
        }

        return (new MineCollection())->export($dto, $filename, $transformedList->toArray());
    }

    #[Transaction]
    public function saveRoomCode($params)
    {
        $data = $this->handleData($params);
        $data['status'] = 1;
        //新增活码
        $codeId = $this->mapper->save($data);
        $roomList = $data['room_list'] ?? [];
        $this->updateRoomRelation($codeId, $roomList, $params['main_uid'],$params['uid']);

        //生成二维码
        $wai = container()->get(SettingConfigService::class)->getConfigByKey('wai_url')['value'];
        $url = $wai . "/?type=2&code=" . $codeId;
        $result = container()->get(ShortChainService::class)->createChains($url);
        $config = [
            'data' => $result['render_url'],
            'size' => 300,
            'margin' => 10,
            'logo' => !empty($params['code_logo']) ? $params['code_logo'] : ''
        ];
        $code = container()->get(QrCode::class)->generation($config, StorageModeConstants::OSS);
        $this->mapper->update($codeId, ['code' => $code, 'render_url' => $result['render_url']]);
        return $codeId;
    }
    #[Transaction]
    public function updateRoomCode($params)
    {
        $data = $this->handleData($params);
        $this->mapper->update($params['id'], $data);
        $roomList = $data['room_list'] ?? [];
        $this->updateRoomRelation((int)$data['id'], $roomList, $params['main_uid'],$params['uid']);
        //删除群命名缓存
        $key = $this->roomNameNumberPrefix . $params['id']. ':' . RoomInviteLogTypeConstants::TYPE_ROOM_CODE;
        $this->redis->del($key);
        return true;
    }

    public function deleteRoomCode($params): bool
    {
        $codeId = (int)$params['id'];

        // 开启事务确保一致性
        return Db::transaction(function () use ($codeId) {

            $this->mapper->delete((array)$codeId);

            $this->roomRelation::query()
                ->where('code_id', $codeId)
                ->delete();

            return true;
        });
    }

    public function getRoomCodeRobotList($params)
    {
        $id = $params['id'];
        $pageSize = (int)$params['page_size'] ?? MineModel::PAGE_SIZE;
        $code = $this->mapper->model::find($id);

        $cfg = $code->room_rule_cfg;
        $robotIds = $cfg['create_room_cfg']['robot_ids'];
        $paginate = $this->robotMapper->model::query()
            ->selectRaw('id,nickname,avatar,corp_name,login_status')
            ->whereIn('id', $robotIds)
            ->paginate($pageSize);
        return $this->mapper->setPaginate($paginate);
    }
    public function updateRelationLimit(array $params)
    {
        $id=$params['id'];
        $visit_limit=$params['visit_limit'];
        $this->roomRelation::query()
            ->where('id', $id)
            ->update(['visit_limit'=>$visit_limit]);
        return true;
    }

    public function addRoomCodeRobot(mixed $params)
    {
        $id = $params['code_id'];
        $newRobotIds = isset($params['robot_ids'])
            ? array_map(
                fn($v) => (int)trim($v),
                array_filter(explode(',', $params['robot_ids']))
            )
            : [];

        $code = $this->mapper->model::find($id);

        $cfg = $code->room_rule_cfg;
        $oldRobotIds = $cfg['create_room_cfg']['robot_ids'];
        $robotIds = array_unique(array_merge($oldRobotIds, $newRobotIds));
        $cfg['create_room_cfg']['robot_ids'] = $robotIds;

        return $this->mapper->update($id, ['room_rule_cfg' => $cfg]);
    }

    public function removeRoomCodeRobot($params)
    {
        $id = $params['code_id'];
        $robotId = (int)$params['robot_id'];


        $code = $this->mapper->model::find($id);

        $cfg = $code->room_rule_cfg;
        $oldRobotIds = $cfg['create_room_cfg']['robot_ids'];
        // 1. 移除指定 robot_id
        $robotIds = array_diff($oldRobotIds, [$robotId]);

        // 2. 重置键值为连续索引
        $robotIds = array_values($robotIds);

        // 3. 确保元素为整数（可选）
        $robotIds = array_map('intval', $robotIds);

        // 4. 更新配置
        $cfg['create_room_cfg']['robot_ids'] = $robotIds;

        return $this->mapper->update($id, ['room_rule_cfg' => $cfg]);
    }

    public function getRoomCodeRoomList($params)
    {
        $id = (int)$params['id'];
        $uid = (int)$params['uid'];
        $pageSize = (int)$params['page_size'] ?? MineModel::PAGE_SIZE;
        $keyword = data_get($params, 'keyword');

        // 获取基础分页数据
        $build = $this->roomRelation::query()
            ->selectRaw('
            ch_room_code_room_relation.id,
            ch_room_code_room_relation.code_id,
            ch_room_code_room_relation.room_id,
            ch_room_code_room_relation.status,
            ch_room_code_room_relation.allocate_status,
            cr.room_avatar_url as room_avatar,
            cr.room_name as room_name,
            cr.room_member_count as room_member_count,
            crc.visit_type,
            ch_room_code_room_relation.visit_limit,
            ch_room_code_room_relation.total_visit,
            ch_room_code_room_relation.join_visit,
            ch_room_code_room_relation.out_visit,
            FROM_UNIXTIME(cr.create_time) as create_time
        ')
            ->leftJoin('ch_room as cr', 'ch_room_code_room_relation.room_wxid', '=', 'cr.room_wxid')
            ->leftJoin('ch_room_code as crc', 'ch_room_code_room_relation.code_id', '=', 'crc.id')
            ->orderBy('ch_room_code_room_relation.sort')
            ->where('ch_room_code_room_relation.code_id', $id)
            ->where('cr.main_uid', $params['main_uid']);
        if ($keyword) {
            $build->where('cr.room_name', 'like', $keyword . '%');
        }
        $paginate = $build->paginate($pageSize);

        // 提取所有房间ID用于统计查询
        $roomIds = $paginate->getCollection()->pluck('room_id')->filter()->unique()->toArray();

        // 批量获取统计信息（需要先实现批量查询方法）
        //$statistics = $this->codeRecordMapper->getCodeStatisticsByRoomIds($uid, $roomIds);

        // 合并统计信息到分页数据
        $paginate->getCollection()->transform(function ($item){
            $item->statistics =[
                'entered_total_count' => $item->join_visit,
                'total_count' => $item->total_visit
            ];
            return $item;
        });

        return $this->mapper->setPaginate($paginate);
    }

    public function addRoomCodeRoom($params)
    {
        $codeId = (int)$params['code_id'];
        $code=$this->mapper->findById($codeId);
        $roomIds = isset($params['room_ids'])
            ? array_map(
                fn($v) => (int)trim($v),
                array_filter(explode(',', $params['room_ids']))
            )
            : [];

        Db::beginTransaction();
        try {
            // 获取当前 code_id 的最大 sort 值
            $maxSort = $this->roomRelation::where('code_id', $codeId)->max('sort') ?? 0;

            // 按顺序插入群关系，sort 依次递增
            foreach ($roomIds as $index => $roomId) {
                $room = $this->roomMapper->findById($roomId);
                $this->roomRelation::updateOrInsert(
                    [
                        'main_uid' => $params['main_uid'],
                        'uid' => $params['uid'],
                        'room_wxid' => $room->room_wxid,
                        'create_user_id' => $room->create_user_id,
                        'code_id' => $codeId,
                        'room_id' =>$roomId,
                    ],
                    [
                        'sort' => $maxSort + $index + 1,
                        'is_show' => 1,
                        'daily_visit' => 0,
                        'total_visit' => 0,
                        'visit_limit' => 9999,
                        'status' => 1,
                        'allocate_status' => 1
                    ]
                );
            }

            Db::commit();
        } catch (\Exception $e) {
            Db::rollBack();
            throw $e;
        }

        return true;
    }

    public function changeRoomCodeRoomSort($params)
    {
        $type = data_get($params, 'direction', 'up');
        $codeId = (int)$params['code_id'];
        $roomId = (int)$params['room_id'];

        // 获取当前关联记录
        $currentRelation = $this->roomRelation::where('code_id', $codeId)
            ->where('room_id', $roomId)
            ->first(['code_id', 'room_id', 'sort']);

        if (!$currentRelation) {
            throw new NormalStatusException('记录不存在');
        }

        // 根据类型进行排序处理
        switch ($type) {
            case 'up':
                $this->moveUp($currentRelation);
                break;
            case 'down':
                $this->moveDown($currentRelation);
                break;
            case 'top':
                $this->moveToTop($currentRelation);
                break;
            case 'bottom':
                $this->moveToBottom($currentRelation);
                break;
            default:
                throw new NormalStatusException('无效的操作类型');
        }
    }

    public function getRoomQrcode(array $params)
    {
        $id = (int)$params['chain_code'];
        $code = $this->mapper->model::find($id);

        if (!$code || $code->status != 1) {
            throw new NormalStatusException('群活码不存在或已停用');
        }

        // 获取基础配置
        $visitType = $code->visit_type; // 从主表获取 visit_type
        $autoCreateRoom = (int)($code->room_rule_cfg['auto_create_room'] ?? 0);
        $triggerCreateRoom = (int)($code->room_rule_cfg['trigger_create_room'] ?? 0);
        $qrcodeVcType = (int)($code->qrcode_vc_type ?? 0);

        // 获取所有可用的群关系（status=1 且 allocate_status=1）
        $relations = $this->roomRelation::query()
            ->select('*')
            ->where('code_id', $id)
            ->where('status', 1)
            ->where('allocate_status', 1)
            ->where('room_id', '>', 0)
            ->orderBy('sort')
            ->get();

        if ($relations->isEmpty()) {
            throw new NormalStatusException('没有可用的群组');
        }


        // 过滤出未满员的群，并更新满员群状态为 allocate_status = 2
        $validRooms = [];
        foreach ($relations as $relation) {
            $roomId = $relation->room_id;
            // 检查访问限制
            $visitLimit = $relation->visit_limit ?? 0;

            if ($qrcodeVcType === 0) {
                $isWithinLimit = $relation->total_visit < $visitLimit;
            } else {
                $isWithinLimit = $relation->daily_visit < $visitLimit;
            }

            if ($isWithinLimit) {
                $validRooms[] = [
                    'room_id' => $roomId,
                    'room_wxid' => $relation->room_wxid,
                    'relation_id' => $relation->id,
                    'sort' => $relation->sort,
                ];
            } else {
                $this->roomRelation::where('code_id', $id)
                    ->where('room_id', $roomId)
                    ->update(['allocate_status' => 2]);
            }
        }
        var_dump('有效群');
        var_dump($validRooms);
        // 自动建群逻辑
        if ($autoCreateRoom && count($validRooms) < $triggerCreateRoom) {
            try {
                co(function ()use($code){
                    $this->createRoomByCode($code);
                });
                //return $this->getRoomQrcode($params); // 递归调用
            } catch (\Exception $e) {
                throw new NormalStatusException('无法自动创建新群：' . $e->getMessage());
            }
        }

        if (empty($validRooms)) {
            throw new NormalStatusException('没有可用的群组');
        }

        // 根据 visit_type 决定选取策略
        switch ($visitType) {
            case 2:
                // 随机跳转
                $selected = $validRooms[array_rand($validRooms)];
                break;

            case 3:
                // 轮询访问（需记录访问次数）
                usort($validRooms, fn($a, $b) => $a['sort'] <=> $b['sort']);
                $selected = $this->getNextValidRoomByRotation($validRooms);
                break;

            case 4:
                // 顺序切换（始终选第一个）
                usort($validRooms, fn($a, $b) => $a['sort'] <=> $b['sort']);
                $selected = $validRooms[0];
                break;

            default:
                throw new NormalStatusException('不支持的访问方式');
        }

        $roomId = $selected['room_id'];
        $room = $this->roomMapper->findById($selected['room_id']);

        // 创建扫码记录(扫码不用记录了)
        $this->codeRecordMapper->model::create([
            'uid' => $code->uid,
            'main_uid' => $code->main_uid,
            'code_id' => $id,
            'room_id' => $roomId,
            'room_wxid' => $room->room_wxid,
            'is_enter_room' => 0,
            'is_out_room' => 0,
            'relation_id' => $selected['relation_id'],
        ]);
        //更新扫码数量
        $this->roomRelation::query()->where(['id'=>$selected['relation_id']])->update([
            'total_visit' => Db::raw('total_visit+1'),
            'daily_visit' => Db::raw('daily_visit+1'),
        ]);
        $this->mapper->update($id, [
            'total_visit' => Db::raw('total_visit+1'),
            'daily_visit' => Db::raw('daily_visit+1'),
        ]);
        $qrCode = [
            'qr_code' => $this->roomService->getQrCode(['id' => $roomId]),
            'chain_type' => 2,
            'is_advanced' => $code->is_advanced,
        ];
        $page_cfg = $code->page_cfg;
        $qrCode['activity_desc'] = data_get($page_cfg, 'activity_desc', '');
        $qrCode['activity_title'] = data_get($page_cfg, 'activity_title', '');
        //长按引导提示
        $qrCode['btn_type'] = data_get($page_cfg, 'scan_tips', 0);
        //安全认证标识
        $qrCode['is_security'] = data_get($page_cfg, 'is_security', 0);
        $qrCode['wechat_qrcode'] = data_get($page_cfg, 'wechat_qrcode', '');
        $qrCode['contact_number'] = data_get($page_cfg, 'contact_number', '');
        $qrCode['is_technical_support'] = 0;
        return $qrCode;
    }

    public function reset(): void
    {
        $this->mapper->model::query()->update(['daily_visit' => 0, 'daily_join_visit' => 0,'daily_out_visit'=>0]);
        $this->roomRelation::query()->update(['daily_visit' => 0, 'daily_join_visit' => 0,'daily_out_visit'=>0]);
    }


    /**
     * 获取群信息
     * @param int $codeId
     * @param array $roomList
     * @return void
     * @throws \Psr\Container\ContainerExceptionInterface
     * @throws \Psr\Container\NotFoundExceptionInterface
     */
//    public function getRoomsQrInfo(array $params)
//    {
//        $roomIds=json_decode($params['room_ids'],true);
//        $roomIds=[584];
//        $roomList=[];
//        foreach ($roomIds as $roomId)
//        {
//            $qrCode=$this->roomService->getQrCode(['id' => $roomId]);
//            $roomList[]=[
//                'room_id' => $roomId,
//                'sort' => 1,
//                'is_show' => 1,
//                'visit_limit' => 9999,
//                //'qr_code' => 'https://img.weikecms.cn/uploadfile/20250526/785463515848888320.jpg',
//                'qr_code' => $qrCode
//            ];
//        }
//        return $roomList;
//    }


    private function moveUp($currentRelation)
    {
        // 获取同code_id下比当前sort小的最大记录
        $previousRelation = $this->roomRelation::where('code_id', $currentRelation->code_id)
            ->where('sort', '<', $currentRelation->sort)
            ->orderByDesc('sort')
            ->first(['code_id', 'room_id', 'sort']);

        if ($previousRelation) {
            Db::transaction(function () use ($currentRelation, $previousRelation) {
                // 使用update精准更新
                $this->roomRelation::where([
                    'code_id' => $currentRelation->code_id,
                    'room_id' => $currentRelation->room_id
                ])->update(['sort' => $previousRelation->sort]);

                $this->roomRelation::where([
                    'code_id' => $previousRelation->code_id,
                    'room_id' => $previousRelation->room_id
                ])->update(['sort' => $currentRelation->sort]);
            });
        }
    }

    private function moveDown($currentRelation)
    {
        // 获取同code_id下比当前sort大的最小记录
        $nextRelation = $this->roomRelation::where('code_id', $currentRelation->code_id)
            ->where('sort', '>', $currentRelation->sort)
            ->orderBy('sort')
            ->first(['code_id', 'room_id', 'sort']);

        if ($nextRelation) {
            Db::transaction(function () use ($currentRelation, $nextRelation) {
                // 使用update精准更新
                $this->roomRelation::where([
                    'code_id' => $currentRelation->code_id,
                    'room_id' => $currentRelation->room_id
                ])->update(['sort' => $nextRelation->sort]);

                $this->roomRelation::where([
                    'code_id' => $nextRelation->code_id,
                    'room_id' => $nextRelation->room_id
                ])->update(['sort' => $currentRelation->sort]);
            });
        }
    }

    private function moveToTop($currentRelation)
    {
        Db::transaction(function () use ($currentRelation) {
            $this->roomRelation::where('code_id', $currentRelation->code_id)
                ->where('room_id', '<>', $currentRelation->room_id)
                ->where('sort', '<', $currentRelation->sort)
                ->increment('sort');

            // 设置当前记录为1
            $this->roomRelation::where([
                'code_id' => $currentRelation->code_id,
                'room_id' => $currentRelation->room_id
            ])->update(['sort' => 1]);
        });
    }

    private function moveToBottom($currentRelation)
    {
        $maxSort = $this->roomRelation::where('code_id', $currentRelation->code_id)
            ->max('sort') ?: 0;
        Db::transaction(function () use ($currentRelation, $maxSort) {
            $this->roomRelation::where('code_id', $currentRelation->code_id)
                ->where('sort', '>', $currentRelation->sort)
                ->decrement('sort');

            // 设置当前记录为最大
            $this->roomRelation::where([
                'code_id' => $currentRelation->code_id,
                'room_id' => $currentRelation->room_id
            ])->update(['sort' => $maxSort]);
        });

    }

    private function updateRoomRelation(int $codeId, array $roomList, mixed $mainUid,mixed $uid)
    {
        $oldRoomIds = $this->roomRelation::where('code_id', $codeId)->where('is_new_create', 0)->pluck('room_id')->toArray();
        $newRoomIds = array_column($roomList, 'room_id');
        // 删除在旧列表但不在新列表中的房间关系
        $toDeleteIds = array_diff($oldRoomIds, $newRoomIds);
        if (!empty($toDeleteIds)) {
            $this->roomRelation::where('code_id', $codeId)
                ->whereIn('room_id', $toDeleteIds)
                ->delete();
        }
        foreach ($roomList as $key => $roomInfo) {
            //查询建群机器人user_id
            $room = container()->get(ChRoomMapper::class)->findById($roomInfo['room_id']);
            $this->roomRelation::query()->updateOrCreate([
                'main_uid' => $mainUid,
                'uid' => $uid,
                'room_wxid' => $room->room_wxid,
                'create_user_id' => $room->create_user_id,
                'code_id' => $codeId,
                'room_id' => $roomInfo['room_id'],
            ], [
                'sort' => $roomInfo['sort'],
                'is_show' => !empty($roomInfo['is_show'])?$roomInfo['is_show']:1,
                'visit_limit' => $roomInfo['visit_limit'],
            ]);
        }
    }


    private function handleData($data)
    {
        $keysToDecode = [
            "page_cfg",
            "room_rule_cfg",
            "room_list"
        ];

        foreach ($keysToDecode as $key) {
            if (isset($data[$key]) && is_string($data[$key])) {
                $decoded = json_decode($data[$key], true);
                if ($decoded !== null) {
                    $data[$key] = $decoded;
                }
            }
        }
        return $data;
    }

    public function createRoomByCode($code): mixed
    {

        $robotIds = $code->room_rule_cfg['create_room_cfg']['robot_ids'];

        $robots = $this->robotMapper->findByIds($robotIds, 'id,login_status')->toArray();

        $onlineRobots = array_filter($robots, function ($robot) {
            return $robot['login_status'] == 1;
        });

        if (empty($onlineRobots)) {
            throw new NormalStatusException('暂无机器人在线');
        }

        $robot = $onlineRobots[array_rand($onlineRobots)];

        $robotId = $robot['id'];
        $robotInfo = $this->robotMapper->findById($robotId);

        $codeId = $code->id;

        $memberList = [];
        $createRule = $code->room_rule_cfg['create_room_cfg']['create_room_rule'] ?? [];
        // 3. 构建成员列表
        $fixedMembers = $createRule['fixed_members'] ?? [];
        foreach ($fixedMembers as $member) {
            if ($member['robot_id'] == $robotId) {
                $memberList = array_merge($memberList, $member['user_ids'] ?? []);
            }
        }
        !empty($createRule['create_room_cfg']['emploee_members']) && $memberList=array_unique(array_merge($memberList, $createRule['create_room_cfg']['emploee_members'] ?? []));
        $robotApiService = make(Robot::class,[$robotInfo->server_id, $robotInfo->uuid])->gateway();
        logger()->info('群活码创建群'.json_encode($memberList));
        $result = $robotApiService->createRoom(array_unique($memberList));
        if ($result === false) {
            throw new NormalStatusException('群创建失败');
        }
        logger()->info('群活码创建群成功');

        $maxSort = $this->roomRelation::where('code_id', $code->id)
            ->max('sort') ?? 0;
        //保存群关系
        $relation=$this->roomRelation::create([
            'create_user_id' => $robotInfo->user_id,
            'room_wxid' => $result['room_id'],
            'code_id' => $codeId,
            'main_uid' => $code->main_uid,
            'uid' => $code->uid,
            'status' => 1,
            'allocate_status' => 1,
            'room_id' => 0,
            'sort' => $maxSort + 1,
            'is_show' => 1,
            'is_new_create' => 1,
            'daily_visit' => 0,
            'total_visit' => 0,
            'visit_limit' => 9999
        ]);
        //异步编辑群名称
        // 1. 获取群编号
        $redis = $this->redis;
        $key = $this->roomNameNumberPrefix . $code->id . ':' . RoomInviteLogTypeConstants::TYPE_ROOM_CODE;

        // 1. 获取群编号（原子操作）
        $roomNameNumber = $redis->incr($key);
        if (empty($roomNameNumber)) { // 首次需要设置初始值
            $initialNo = $code->room_rule_cfg['create_room_cfg']['create_room_rule']['no'] ?? 1;
            $roomNameNumber = $redis->set($key, $initialNo) ? $initialNo : 1;
        }

        // 2. 获取基础配置
        $createRule = $code->room_rule_cfg['create_room_cfg']['create_room_rule'] ?? [];
        $roomName = $createRule['name'] ?? '默认群名称';
        $newRoomName = $roomName . $roomNameNumber;

        $robotApiService->editRoomName($result['room_id'], $newRoomName);
        //打标签放在跟新的时候了
        //$code->room_rule_cfg['auto_add_room_tags'] && $this->addTags($relation->id,$code);
        return $relation;

    }


    /**
     * @param $contact
     * @return void
     * @throws \Psr\Container\ContainerExceptionInterface
     * @throws \Psr\Container\NotFoundExceptionInterface
     * 打标签
     */
    public function addTags($roomId,$codeId)
    {
        $code=$this->mapper->findById($codeId);
        $roomInfo = $this->roomMapper->findById($roomId);
        $tagIds = explode(',',$code->room_rule_cfg['room_tag_ids']);
        $content = new RoomTcContentDto();
        $content->setRoomIds([$roomInfo->id]);
        $content->setTagIds($tagIds);
        $this->ChRoomTaskCenterService->addTask($roomInfo->uid,$roomInfo->main_uid,RoomTaskCenterTypeConstants::TAG,$content);

    }

    public function addNewCreatedRoom($schemeId, $mainUid, $roomWxid)
    {
        $room = $this->roomMapper->findByRoomWxid($roomWxid, $mainUid);
        $maxSort = $this->roomRelation::where('code_id', $schemeId)
            ->max('sort') ?? 0;
        $this->roomRelation::updateOrInsert(
            [
                'code_id' => $schemeId,
                'room_id' => $room->id
            ],
            [
                'status' => 1,
                'sort' => $maxSort + 1,
                'allocate_status' => 1,
                'is_new_create' => 1,
                'is_show' => 1,
                'daily_visit' => 0,
                'total_visit' => 0,
                'visit_limit' => 9999,
            ]
        );
    }

    public function markUserAsEntered($uid, $userIds, $roomWxId): void
    {
        $members = ChRoomMember::query()
            ->where('room_wxid', $roomWxId)
            ->whereIn('user_id', $userIds)
            ->where('join_scene', 3) // 仅处理扫码入群的用户
            ->get(['user_id']);

        if (empty($members))
            return;

        // 提取有效的 userIds
        $validUserIds = $members->pluck('user_id')->toArray();

        $this->codeRecordMapper->model::query()
            ->where('room_wxid', $roomWxId)
            ->whereIn('user_id', $validUserIds)
            ->update(['is_out_room' => 1]);
    }

    public function markUserAsExited($userIds, $roomWxId): void
    {
        $this->codeRecordMapper->model::query()
            ->whereIn('user_id', $userIds)
            ->where('room_wxid', $roomWxId)
            ->update(['is_out_room' => 1]);
    }

    public function syncRelationRoomId(mixed $mainUid, mixed $roomWxId,mixed $roomId)
    {
        $relation=$this->roomRelation::query()
            ->where('main_uid', $mainUid)
            ->where('room_wxid', $roomWxId)
            ->first();
        if(empty($relation)){
            return null;
        }
        if($relation['room_id'] > 0){
            return null;
        }
        $relation->update(['room_id' => $roomId]);
        return $relation['code_id'];
    }

    private function getNextValidRoomByRotation(array $validRooms)
    {
        // 检查是否所有群都已满员
        if (empty($validRooms)) {
            throw new NormalStatusException('没有可用的群组');
        }

        $codeId = data_get($validRooms[0], 'code_id', 0); // 假设 code_id 在 validRooms 中
        $key = "rotation:index:{$codeId}";

        // 获取当前索引（原子操作）
        $currentIndex = $this->redis->incr($key);

        // 设置过期时间（每日重置）
        if ($this->redis->ttl($key) <= 0) {
            $this->redis->expire($key, 86400);
        }

        // 计算实际索引
        $index = ($currentIndex - 1) % count($validRooms);

        return $validRooms[$index];
    }

}